﻿using System;
using System.Linq.Expressions;
using System.Reflection;
using Xtensive.Core;
using Xtensive.Orm;

namespace LinqCustomCompiler.Model
{
  [CompilerContainer(typeof (Expression))] // Defines compiler collection
  public static class LinqCompilers
  {
    // Defines compiler for type "Order" and member "TotalPrice".
    // Compiler is used for translating property getter.
    [Compiler(typeof (Order), "TotalPrice", TargetKind.PropertyGet)]
    public static Expression OrderTotalPrice(Expression order)
    {
      Expression<Func<Order, decimal>> orderTotal = o => o.ItemCount * o.ItemPrice;
      // This helper method substitues lambda parameters with specified values.
      return orderTotal.BindParameters(order);
    }

    // Defines compiler for type "ComparisonExtensions" and method "GreaterThan".
    // The last argument to CompilerAttribute constructor is a number of generic arguments
    // if target is a generic member.
    // Compiler is used for translating static method access.
    // Note that compilers for generic members should have extra MemberInfo argument.
    [Compiler(typeof (ComparisonExtensions), "GreaterThan", TargetKind.Static | TargetKind.Method, 1)]
    public static Expression GreaterThan(MemberInfo member, Expression left, Expression right)
    {
      var call = Expression.Call(left, "CompareTo", null, right);
      return Expression.GreaterThan(call, Expression.Constant(0));
    }
  }
}